import { PaymentMethodType, Topup, TopupService, TopupStatus } from "@mallfoundry/finance"
import { Button, Card, Col, DatePicker, Divider, Form, Popconfirm, Radio, Row, Select, Space, Table, Tabs, Typography } from "antd"
import { RadioChangeEvent } from "antd/lib/radio"
import { ColumnProps } from "antd/lib/table"
import * as dayjs from "dayjs"
import * as _ from "lodash"
import * as React from "react"
import { useEffect, useState } from "react"
import { useHistory, useLocation, useParams } from "react-router-dom"
import Page from "../../components/page"
import { useTopups } from "../../hooks/finance"
import { useStore } from "../../hooks/store"
import classes from "./topup-list.module.scss"

const { Text, Link: TextLink } = Typography
const { TabPane } = Tabs
const { RangePicker } = DatePicker

const layout = {
  labelCol: { span: 6 },
  wrapperCol: { span: 18 },
}

function statusToLabel(status: TopupStatus) {
  if (status === TopupStatus.Pending) {
    return "充值中"
  } else if (status === TopupStatus.Canceled) {
    return "已取消"
  } else if (status === TopupStatus.Succeeded) {
    return "充值成功"
  } else if (status === TopupStatus.Failed) {
    return "充值失败"
  }
}

function renderStatus(status: TopupStatus) {
  const statusLabel = statusToLabel(status)
  if (status === TopupStatus.Succeeded) {
    return <Text type="success">{statusLabel}</Text>
  }
  return statusLabel
}

function renderChannel(methodType: PaymentMethodType) {
  if (methodType === PaymentMethodType.AliPay) {
    return "支付宝"
  } else if (methodType === PaymentMethodType.WechatPay) {
    return "微信支付"
  }
  return methodType
}

const BASE_COLUMNS: ColumnProps<Topup>[] = [
  {
    title: "流水号",
    key: "id",
    dataIndex: "id",
  },
  {
    title: "充值金额（元）",
    key: "amount",
    dataIndex: "amount",
    align: "right",
    width: "160px",
    render: amount => _.toNumber(amount).toFixed(2),
  },
  {
    title: "充值状态",
    dataIndex: "status",
    key: "status",
    align: "center",
    render: renderStatus,
  },
  {
    title: "支付方式",
    dataIndex: "channel",
    key: "channel",
    align: "center",
    render: renderChannel,
  },
  {
    title: "操作人",
    dataIndex: "operator",
    key: "operator",
  },
  {
    title: "充值时间",
    dataIndex: "createdTime",
    key: "createdTime",
    width: "160px",
  },
]

interface TopupCancelButtonProps {
  topupId: string
  onCanceled: () => void
}

function TopupCancelButton({ topupId, onCanceled }: TopupCancelButtonProps) {
  const [cancelLoading, setCancelLoading] = useState(false)
  const [cancelVisible, setCancelVisible] = useState(false)

  function handleCancel() {
    setCancelLoading(true)
    TopupService
      .cancelTopup(topupId)
      .then(onCanceled)
      .finally(() => setCancelLoading(false))
  }

  return <Popconfirm visible={cancelVisible || cancelLoading}
                     placement="bottomRight" title="您确定要取消吗？"
                     okButtonProps={{ loading: cancelLoading }}
                     onConfirm={handleCancel}
                     onVisibleChange={setCancelVisible}>
    <TextLink onClick={() => setCancelVisible(!cancelVisible)}>取消</TextLink>
  </Popconfirm>
}

export default function TopupList() {
  const history = useHistory()
  const location = useLocation()
  const searchParams = new URLSearchParams(location.search)
  const page = searchParams.get("page") ?? 1
  const limit = searchParams.get("limit") ?? 20
  const statuses = searchParams.get("statuses") ?? ""
  const channels = searchParams.get("channels") ?? ""
  const createdTimeStart = searchParams.get("created_time_start") ?? ""
  const createdTimeEnd = searchParams.get("created_time_end") ?? ""

  const { storeId } = useParams<{ storeId: string }>()

  const [customCreatedTimes, setCustomCreatedTimes] = useState(0)
  const { store: { accountId } } = useStore(storeId)

  const {
    loading,
    elements: topups,
    refresh: refreshTopups,
  } = useTopups({ page, limit, accountId, statuses, createdTimeStart, createdTimeEnd })

  const [form] = Form.useForm()

  const columns: ColumnProps<Topup>[] = [...BASE_COLUMNS, {
    title: "操作",
    dataIndex: "id",
    key: "id",
    align: "right",
    width: "140px",
    render: (id: string, { status }: Topup) => <Space align="center">
      {status === TopupStatus.Pending && <>
        <TextLink>支付</TextLink>
        <Divider type="vertical" style={{ margin: 0 }}/>
        <TopupCancelButton topupId={id} onCanceled={refreshTopups}/>
      </>}
    </Space>,
  }]

  useEffect(() => {
    form.setFieldsValue({
      statuses, channels,
      createdTimes: [
        createdTimeStart ? dayjs(createdTimeStart) : undefined,
        createdTimeEnd ? dayjs(createdTimeEnd) : undefined,
      ],
    })
    handleSetCustomCreatedTimes([createdTimeStart, createdTimeEnd])
  }, [form, statuses, channels, createdTimeStart, createdTimeEnd])

  function handleChangeCreatedTimes(e: RadioChangeEvent) {
    const aCustomCreatedTimes = e.target.value
    setCustomCreatedTimes(aCustomCreatedTimes)
    if (aCustomCreatedTimes === -7) {
      form.setFieldsValue({ createdTimes: [dayjs().add(-6, "day"), dayjs()] })
    } else if (aCustomCreatedTimes === -30) {
      form.setFieldsValue({ createdTimes: [dayjs().add(-29, "day"), dayjs()] })
    }
  }

  function handleSetCustomCreatedTimes(dateStrings: [string, string]) {
    const [dateStart, dateEnd] = dateStrings
    const today = dayjs().format("YYYY-MM-DD")
    const in7day = dayjs().add(-6, "day").format("YYYY-MM-DD")
    const in30day = dayjs().add(-29, "day").format("YYYY-MM-DD")
    if (dateStart === in7day && dateEnd === today) {
      setCustomCreatedTimes(-7)
    } else if (dateStart === in30day && dateEnd === today) {
      setCustomCreatedTimes(-30)
    } else {
      setCustomCreatedTimes(0)
    }
  }

  function handleSearch() {
    form.validateFields()
      .then(values => {
        const { statuses, channels, createdTimes } = values
        if (statuses) {
          searchParams.set("statuses", statuses)
        } else {
          searchParams.delete("statuses")
        }
        if (channels) {
          searchParams.set("channels", channels)
        } else {
          searchParams.delete("channels")
        }
        if (createdTimes) {
          const [createdTimeStart, createdTimeEnd] = createdTimes
          if (createdTimeStart) {
            searchParams.set("created_time_start", dayjs(createdTimeStart).format("YYYY-MM-DD"))
          } else {
            searchParams.delete("created_time_start")
          }
          if (createdTimeEnd) {
            searchParams.set("created_time_end", dayjs(createdTimeEnd).format("YYYY-MM-DD"))
          } else {
            searchParams.delete("created_time_end")
          }
        } else {
          searchParams.delete("created_time_start")
          searchParams.delete("created_time_end")
        }
        history.replace(_.assign(location, {
          search: `?${searchParams.toString()}`,
        }))
      })
  }

  function handleReset() {
    history.push(_.assign(location, {
      search: ``,
    }))
  }

  return (
    <div className={classes.TopupList}>
      <Page.Header title="充值记录" ghost={false}/>
      <Page.Content>
        <Card>
          <Tabs activeKey="2" animated={false} onChange={(tabKey: string) => {
            if (tabKey === "1") {
              history.push(`/stores/${storeId}/topups/new`)
            }
          }}>
            <TabPane tab="充值" key="1"/>
            <TabPane tab="充值记录" key="2">
              <Row gutter={[16, 16]}>
                <Col span={24}>
                  <Card className={classes.FilterBar} bordered={false}>
                    <Form {...layout} form={form}>
                      <Row>
                        <Col span={6}>
                          <Form.Item label="充值时间" name="createdTimes">
                            <RangePicker style={{ width: "100%" }}
                                         onChange={(dates, dateStrings) => handleSetCustomCreatedTimes(dateStrings)}/>
                          </Form.Item>
                        </Col>
                        <Col span={6}>
                          <Radio.Group style={{ marginLeft: "8px" }} value={customCreatedTimes} onChange={handleChangeCreatedTimes}>
                            <Space>
                              <Radio.Button value={-7} className={classes.PlacedDateButton}>近7天</Radio.Button>
                              <Radio.Button value={-30} className={classes.PlacedDateButton}>近30天</Radio.Button>
                            </Space>
                          </Radio.Group>
                        </Col>
                      </Row>
                      <Row>
                        <Col span={6}>
                          <Form.Item name="statuses" label="提现状态">
                            <Select>
                              <Select.Option value="">全部</Select.Option>
                              <Select.Option value={TopupStatus.Pending}>充值中</Select.Option>
                              <Select.Option value={TopupStatus.Canceled}>充值已取消</Select.Option>
                              <Select.Option value={TopupStatus.Succeeded}>充值成功</Select.Option>
                              <Select.Option value={TopupStatus.Failed}>充值失败</Select.Option>
                            </Select>
                          </Form.Item>
                        </Col>
                        <Col span={6}>
                          <Form.Item name="channels" label="支付方式">
                            <Select>
                              <Select.Option value="">全部</Select.Option>
                              <Select.Option value={PaymentMethodType.WechatPay}>微信支付</Select.Option>
                              <Select.Option value={PaymentMethodType.AliPay}>支付宝</Select.Option>
                            </Select>
                          </Form.Item>
                        </Col>
                      </Row>
                      <Row>
                        <Col span={6}>
                          <Row>
                            <Col offset={6}>
                              <Space>
                                <Button type="primary" onClick={handleSearch} loading={loading}>筛选</Button>
                                <Button onClick={handleReset}>重置</Button>
                              </Space>
                            </Col>
                          </Row>
                        </Col>
                      </Row>
                    </Form>
                  </Card>
                </Col>
              </Row>
              <Row>
                <Col span={24}>
                  <Table rowKey="id" loading={loading} columns={columns} dataSource={topups}/>
                </Col>
              </Row>
            </TabPane>
          </Tabs>
        </Card>
      </Page.Content>
    </div>
  )
}
